/*
 * The MIT License
 *
 * Copyright 2014 David Rodenas Pico.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package edu.uoc.sd.fr14.actors;

import edu.uoc.sd.fr14.model.CustomerId;
import edu.uoc.sd.fr14.model.FlightId;
import edu.uoc.sd.fr14.model.OpId;
import edu.uoc.sd.fr14.model.ServerId;

/**
 * This interface represents the clock actor.
 * 
 * You should use a provided instance of this actor through Cluster 
 * instead of programming your own clock
 * because it provides advanced concurrent and cancel management features.
 * 
 * @author drodenas
 */
public interface Clock {
    
	/**
	 * Request to the timeout to cancel a prepare message timeout.
	 * <p>
	 * You should invoke this method when there were enough prepare
	 * answers to know that you do not need more servers.
	 * <p>
	 * Nothing happens if you cancel a non-existing timer.
	 * <p>
	 * If this timer is called from the from server,
	 * before the timeout is triggered,  
	 * it ensures that the timeout will never fire.
	 *  
	 * @param op   operation id associated of a waiting prepared
	 * @param from server who invoked setPrepareTo 
	 */
    void cancelPrepareTo(OpId op, ServerId from);
    
	/**
	 * Request to the timeout to cancel a timeout from a seat operation.
	 * <p>
	 * You should invoke this method from a follower server when you
	 * have received a confirmed message from the leader as answer
	 * to a seat.
	 * <p>
	 * Nothing happens if you cancel a non-existing timer.
	 * <p>
	 * If this timer is called from the from server,
	 * before the timeout is triggered,  
	 * it ensures that the timeout will never fire.
	 *  
     * @param flight   flight of the seat operation that set the timer
     * @param customer customer of the seat operation that set the timer
     * @param from     server who invoked setPrepareTo
     */
    void cancelSeatTo(FlightId flight, CustomerId customer, ServerId from);
    
    /**
     * Request to set an election timeout.
     * <p>
     * 
     * You should set this timeout when you want to start
     * an election if no other event happens. 
     * 
     * @param from the server which sets the timeout
     */
    void setElectionTo(ServerId from);
    
    /**
     * Request to set a timeout to ensure prepare operations.
     * <p>
     * 
     * You should set this timeout when a server receives a seat operation
     * and you send many prepare operations o other servers. 
     * It will help to know if other servers are online if they responds
     * before timeout is triggered (you should cancel it if you have 
     * enough answers).
     * <p>
     * 
     * Note that the operation id (op) is the same used in the prepare
     * message and used in the cancelPrepareTo. Is the way that the system
     * knows which of all concurrent operations is.
     * 
     * @param op   is the operation id generated from the received seat operation
     * @param from is the server which requests the timeout
     */
    void setPrepareTo(OpId op, ServerId from);
    
    /**
     * Request to set a timeout at follower 
     * to ensure that the leader executes a forwarded seat operation.
     * <p>
     * 
     * You should set this timeout when you are a follower, 
     * you receive a seat operation, and you redirect this seat
     * operation to a leader. 
     * If the leader do not confirmed fast enough to the seat
     * operation (may be is down), the timeout is triggered.
     * You should cancel as soon as correspondent confirmed is received.
     * <p> 
     * 
     * Note that flight and customer matches with the ones of the seat
     * operation, and they are used to know that the server responds 
     * with confirmed of the same flight/customer operation.
     * 
     * @param flight   the flight of the received seat operation
     * @param customer the customer of the received seat operation
     * @param from     the follower server which sets the timeout
     */
    void setSeatTo(FlightId flight, CustomerId customer, ServerId from);
    
}
